﻿namespace Smart.Utils.Localization
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Resources;

    public class ResourceEnumConverter : EnumConverter
    {
        private Array _flagValues;
        private bool _isFlagEnum;
        private Dictionary<CultureInfo, LookupTable> _lookupTables;
        private ResourceManager _resourceManager;

        public ResourceEnumConverter(Type type, ResourceManager resourceManager) : base(type)
        {
            this._lookupTables = new Dictionary<CultureInfo, LookupTable>();
            this._isFlagEnum = false;
            this._resourceManager = resourceManager;
            object[] customAttributes = type.GetCustomAttributes(typeof(FlagsAttribute), true);
            this._isFlagEnum = customAttributes.Length > 0;
            if (this._isFlagEnum)
            {
                this._flagValues = Enum.GetValues(type);
            }
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (culture == null)
            {
                culture = CultureInfo.CurrentCulture;
            }
            if (value is string)
            {
                object obj2 = this._isFlagEnum ? this.GetFlagValue(culture, (string) value) : this.GetValue(culture, (string) value);
                if (obj2 == null)
                {
                    obj2 = base.ConvertFrom(context, culture, value);
                }
                return obj2;
            }
            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (culture == null)
            {
                culture = CultureInfo.CurrentCulture;
            }
            if ((value != null) && (destinationType == typeof(string)))
            {
                return (this._isFlagEnum ? this.GetFlagValueText(culture, value) : this.GetValueText(culture, value));
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

        public static string ConvertToString(Enum value)
        {
            return TypeDescriptor.GetConverter(value.GetType()).ConvertToString(value);
        }

        private object GetFlagValue(CultureInfo culture, string text)
        {
            LookupTable lookupTable = this.GetLookupTable(culture);
            string[] strArray = text.Split(new char[] { ',' });
            ulong num = 0L;
            foreach (string str in strArray)
            {
                object obj2 = null;
                string key = str.Trim();
                if (!lookupTable.TryGetValue(key, out obj2))
                {
                    return null;
                }
                num |= Convert.ToUInt32(obj2);
            }
            return Enum.ToObject(base.EnumType, num);
        }

        private string GetFlagValueText(CultureInfo culture, object value)
        {
            if (Enum.IsDefined(value.GetType(), value))
            {
                return this.GetValueText(culture, value);
            }
            ulong num = Convert.ToUInt32(value);
            string str = null;
            foreach (object obj2 in this._flagValues)
            {
                ulong num2 = Convert.ToUInt32(obj2);
                if (this.IsSingleBitValue(num2) && ((num2 & num) == num2))
                {
                    string valueText = this.GetValueText(culture, obj2);
                    if (str == null)
                    {
                        str = valueText;
                    }
                    else
                    {
                        str = string.Format("{0}, {1}", str, valueText);
                    }
                }
            }
            return str;
        }

        private LookupTable GetLookupTable(CultureInfo culture)
        {
            LookupTable table = null;
            if (culture == null)
            {
                culture = CultureInfo.CurrentCulture;
            }
            if (!this._lookupTables.TryGetValue(culture, out table))
            {
                table = new LookupTable();
                foreach (object obj2 in base.GetStandardValues())
                {
                    string valueText = this.GetValueText(culture, obj2);
                    if (valueText != null)
                    {
                        table.Add(valueText, obj2);
                    }
                }
                this._lookupTables.Add(culture, table);
            }
            return table;
        }

        private object GetValue(CultureInfo culture, string text)
        {
            LookupTable lookupTable = this.GetLookupTable(culture);
            object obj2 = null;
            lookupTable.TryGetValue(text, out obj2);
            return obj2;
        }

        public static List<KeyValuePair<Enum, string>> GetValues(Type enumType)
        {
            return GetValues(enumType, CultureInfo.CurrentUICulture);
        }

        public static List<KeyValuePair<Enum, string>> GetValues(Type enumType, CultureInfo culture)
        {
            List<KeyValuePair<Enum, string>> list = new List<KeyValuePair<Enum, string>>();
            TypeConverter converter = TypeDescriptor.GetConverter(enumType);
            foreach (Enum enum2 in Enum.GetValues(enumType))
            {
                KeyValuePair<Enum, string> item = new KeyValuePair<Enum, string>(enum2, converter.ConvertToString(null, culture, enum2));
                list.Add(item);
            }
            return list;
        }

        private string GetValueText(CultureInfo culture, object value)
        {
            Type type = value.GetType();
            string name = string.Format("{0}_{1}", type.Name, value.ToString());
            string str2 = this._resourceManager.GetString(name, culture);
            if (str2 == null)
            {
                str2 = name;
            }
            return str2;
        }

        private bool IsSingleBitValue(ulong value)
        {
            ulong num = value;
            if ((num <= 1L) && (num >= 0L))
            {
                switch (((int) num))
                {
                    case 0:
                        return false;

                    case 1:
                        return true;
                }
            }
            return ((value & (value - ((ulong) 1L))) == 0L);
        }

        private class LookupTable : Dictionary<string, object>
        {
        }
    }
}

